using System;
using System.Collections;
using System.Text;

using Lucene.Net.Index;
using Lucene.Net.Documents;
using Lucene.Net.Analysis.Standard;

namespace GURUCORE.Framework.Core.Indexing
{
	public class Indexer
	{
		public const int INDEX_READ = 1;
		public const int INDEX_WRITE = 2;
		public const int INDEX_READWRITE = 3;

		IndexReader m_oReader;
		IndexWriter m_oWriter;

		public Indexer(int p_nOption, string p_sFolder)
		{
			if ((p_nOption & INDEX_WRITE) == INDEX_WRITE)
			{
				try
				{
					m_oWriter = new IndexWriter(p_sFolder, new StandardAnalyzer(), false);
				}
				catch
				{
					m_oWriter = new IndexWriter(p_sFolder, new StandardAnalyzer(), true);
				}
			}

			if ((p_nOption & INDEX_READ) == INDEX_READ)
			{
				m_oReader = IndexReader.Open(p_sFolder);
			}
		}

		public Indexer(int p_nOption)
		{
			if ((p_nOption & INDEX_WRITE) == INDEX_WRITE)
			{
				try
				{
					m_oWriter = new IndexWriter(GApplication.GetInstance().RootDir + "\\Data\\System\\Index", new StandardAnalyzer(), false);
				}
				catch
				{
					m_oWriter = new IndexWriter(GApplication.GetInstance().RootDir + "\\Data\\System\\Index", new StandardAnalyzer(), true);
				}
			}

			if ((p_nOption & INDEX_READ) == INDEX_READ)
			{
				m_oReader = IndexReader.Open(GApplication.GetInstance().RootDir + "Data\\System\\Index");
			}
		}

        /// <summary>
        /// __Content__ Field is the field to get result
        /// __DOmain__   __Document__ __ID__ is  mark (meta data) field, for GURUCORE ENgine to identify the reality data object (eg: the ID of the Trip to find)
        /// </summary>
        /// <param name="p_sDocumentName">can be DTO Name , include prefix</param>
        /// <param name="p_nID">primary key value</param>
        /// <param name="p_htDocument">list of fulltext  to search, eg: TripName=a, TripDetail=B</param>
		public void AddDocument(string p_sDocumentName, int p_nID, Hashtable p_htDocument)
		{
			Document oDocument = new Document();
			Field oDocumentIDField = new Field("__Document#ID__", p_sDocumentName + "#" + p_nID.ToString(), Field.Store.YES, Field.Index.TOKENIZED);
			oDocument.Add(oDocumentIDField);

			string sDomain = string.Empty;
			string sTableName = p_sDocumentName.ToLower();
			if ((p_sDocumentName.IndexOf("_") >= 0) && (p_sDocumentName.IndexOf("_") < p_sDocumentName.Length - 1))
			{
				string[] arrToken = p_sDocumentName.Split('_');
				sDomain = arrToken[0].ToLower();
				sTableName = arrToken[1].ToLower();
			}

			Field oDomainField = new Field("__Domain__", sDomain, Field.Store.YES, Field.Index.TOKENIZED);
			oDocument.Add(oDomainField);

			Field oDocumentField = new Field("__Document__", sTableName, Field.Store.YES, Field.Index.TOKENIZED);
			oDocument.Add(oDocumentField);
			
			Field oIDField = new Field("__ID__", p_nID.ToString(), Field.Store.YES, Field.Index.TOKENIZED);
			oDocument.Add(oIDField);

			string sContent = string.Empty;
			foreach (DictionaryEntry oEntry in p_htDocument)
			{
                if (null != oEntry.Value)
                {
                    sContent += oEntry.Value + "\r\n";   //  "\r\n" is phrase seperator (of Lucense API)
                }
			}
			
			//process utf-8 escape, by temporary
            // we only make index on format of text return by TextHelper.ProcessUtf8Escape() 
			sContent = GURUCORE.Lib.Core.Text.TextHelper.ProcessUtf8Escape(sContent);

			Field oField = new Field("__Content__", sContent, Field.Store.YES, Field.Index.TOKENIZED);
			oDocument.Add(oField);

			m_oWriter.AddDocument(oDocument);
		}

		public void DeleteDocument(string p_sDocumentName, int p_nIDTermValue)
		{
			Term oDocumentIDTerm = new Term("__Document#ID__", p_sDocumentName + "#" + p_nIDTermValue.ToString());

			TermPositions itrPosition = m_oReader.TermPositions(oDocumentIDTerm);
			while (itrPosition.Next())
			{
				m_oReader.DeleteDocument(itrPosition.Doc());
				return;
			}
		}

		public void Commit()
		{
			if (m_oReader != null)
			{
				m_oReader.Close();
			}

			if (m_oWriter != null)
			{
				m_oWriter.SetUseCompoundFile(true);
				m_oWriter.Optimize();
				m_oWriter.Close();
			}
		}
	}
}
